package cn.com.taiji.pos.controller;

import cn.com.taiji.model.finals.SessionNames;
import cn.com.taiji.pos.common.util.SmallTicketPrinter;
import cn.com.taiji.pos.common.util.pay.alipay.zhifubao.config.Configs;
import cn.com.taiji.pos.common.util.pay.alipay.zhifubao.model.builder.AlipayTradePayRequestBuilder;
import cn.com.taiji.pos.common.util.pay.alipay.zhifubao.model.result.AlipayF2FPayResult;
import cn.com.taiji.pos.common.util.pay.alipay.zhifubao.service.AlipayTradeService;
import cn.com.taiji.pos.common.util.pay.alipay.zhifubao.service.impl.AlipayTradeServiceImpl;
import cn.com.taiji.pos.common.util.pay.wxpay.WXPay;
import cn.com.taiji.pos.common.util.pay.wxpay.WXPayConfigImpl;
import cn.com.taiji.pos.entity.*;
import cn.com.taiji.pos.service.*;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.dreamyoung.mprelation.AutoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.WebUtils;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@RestController
@RequestMapping("/StoredAndOffset")
public class CZCZController {

    @Value("${CARD_ACCOUNT_TYPE_CHUZHI}")
    private String CARD_ACCOUNT_TYPE_CHUZHI;
    @Value("${SETTLEMENT_TYPE_ID_jiesuan}")
    private String SETTLEMENT_TYPE_ID_jiesuan;

    @Autowired
    private ICardInfoService cardInfoService;
    @Autowired
    private IConfigMealTimeService configMealTimeService;
    @Autowired
    private ICardCustomerService cardCustomerService;
    @Autowired
    private ICardAccountService cardAccountService;
    @Autowired
    private ISystemAclUserService systemAclUserService;
    @Autowired
    private ISystemAclEmpowerstrikeService systemAclEmpowerstrikeService;
    @Autowired
    private ISystemPosMachineService systemPosMachineService;
    @Autowired
    private ITradeAccountStoreFlowService tradeAccountStoreFlowService;
    @Autowired
    private IConfigBusinessTypeService configBusinessTypeService;
    @Autowired
    private ISystemPrinterService systemPrinterService;
    @Autowired
    public SmallTicketPrinter smallTicketPrinter;
    @Autowired
    private AutoMapper autoMapper;

    static {
        Configs.init("classpath:config/zfbinfo.properties");
    }

    private static AlipayTradeService tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();


    /**
     * 储值冲账
     *
     * @param request
     */
    @RequestMapping(value = "Offset", method = RequestMethod.POST)
    public String offset(Model model, HttpServletRequest request) {
        SystemAclUser user = (SystemAclUser) WebUtils.getSessionAttribute(request, SessionNames.LOGIN_USER);
        model.addAttribute("result", "fail");
        String cardCode = request.getParameter("cardCode");
        String physicalCode = request.getParameter("physicalCode");
        String amount = request.getParameter("amount");
        String reason = request.getParameter("reason");
        CardInfo cardInfo;
        CardCustomer cardCustomer;
        CardAccount cardAccount;
        if (!StringUtils.hasText(amount) || Double.parseDouble(amount) <= 0) {
            model.addAttribute("message", "充值金额不能为零");
            return JSONObject.toJSONString(model);
        } else if (!StringUtils.hasText(reason)) {
            model.addAttribute("message", "冲账原因为空，不能冲账");
            return JSONObject.toJSONString(model);
        }
        //查询顾客卡信息
        QueryWrapper<CardInfo> cardInfoWrapper = new QueryWrapper<>();
        cardInfoWrapper.eq("CARD_CODE", cardCode);
        cardInfoWrapper.eq("status", 0);
        cardInfo = cardInfoService.getOne(cardInfoWrapper);
        if (cardInfo == null) {
            model.addAttribute("message", "未找到该卡片所对应客户");
            return JSONObject.toJSONString(model);
        } else {
//            查询顾客信息
            QueryWrapper<CardCustomer> cardCustomerWrapper = new QueryWrapper<>();
            cardCustomerWrapper.eq("STATUS", 0);
            cardCustomerWrapper.eq("ID", cardInfo.getCustomerId());
            cardCustomer = cardCustomerService.getOne(cardCustomerWrapper);
            if (cardCustomer == null) {
                model.addAttribute("message", "账户已被冻结");
                return JSONObject.toJSONString(model);
            } else {
                //查询账户信息
                QueryWrapper<CardAccount> cardAccountWrapper = new QueryWrapper<>();
                cardAccountWrapper.eq("CUSTOMER_ID", cardInfo.getCustomerId());
                cardAccountWrapper.eq("ACCOUNT_TYPE_ID", CARD_ACCOUNT_TYPE_CHUZHI);
                cardAccountWrapper.eq("STATUS", 0);
                cardAccount = cardAccountService.getOne(cardAccountWrapper);
                if (cardAccount == null) {
                    model.addAttribute("message", "未找到该卡片所对应储值型账户(次数型账户不可进行本操作)");
                    return JSONObject.toJSONString(model);
                }
            }
        }
        //先存储流水
        TradeAccountStoreFlow tradeAccountStoreFlow = new TradeAccountStoreFlow();

        SystemPosMachine systemPosMachine = systemPosMachineService.findByPhysicalCode(physicalCode);
        if (systemPosMachine == null) {
            tradeAccountStoreFlow.setPosMachineId("");
        } else {
            tradeAccountStoreFlow.setPosMachineId(systemPosMachine.getId());
        }
        tradeAccountStoreFlow.setCustomerId(cardCustomer.getId());
        tradeAccountStoreFlow.setAccountId(cardAccount.getId());
        tradeAccountStoreFlow.setCardId(cardInfo.getId());
        tradeAccountStoreFlow.setOperateType(1);
        tradeAccountStoreFlow.setSettlementTypeId(SETTLEMENT_TYPE_ID_jiesuan);//结算
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss");
        tradeAccountStoreFlow.setFlowNo("STRIKE-" + df.format(LocalDateTime.now()) + UUID.randomUUID().toString().substring(0, 4));
        tradeAccountStoreFlow.setBeforeAmount(cardAccount.getAmount());
        tradeAccountStoreFlow.setActualAmount(new BigDecimal(amount));
        tradeAccountStoreFlow.setAfterAmount(new BigDecimal(cardAccount.getAmount().doubleValue() - Double.parseDouble(amount)));
        tradeAccountStoreFlow.setBeforeTimes(0);
        tradeAccountStoreFlow.setAfterTimes(0);
        tradeAccountStoreFlow.setTimes(0);
        tradeAccountStoreFlow.setReasonId(reason);
        tradeAccountStoreFlow.setIsPay("0");
        tradeAccountStoreFlow.setCreatorId(user.getId());
        tradeAccountStoreFlow.setCreatorName(user.getName());
        tradeAccountStoreFlow.setCreateTime(LocalDateTime.now());
        tradeAccountStoreFlowService.save(tradeAccountStoreFlow);
//       再扣钱
        cardAccount.setAmount(tradeAccountStoreFlow.getAfterAmount());
        cardAccountService.updateById(cardAccount);
        tradeAccountStoreFlowService.updateById(tradeAccountStoreFlow);
        model.addAttribute("result", "success");
        model.addAttribute("message", "冲账成功");
        return JSONObject.toJSONString(model);
    }


    /**
     * 储值
     *
     * @param request
     */
    @RequestMapping(value = "Stored", method = RequestMethod.POST)
    public String stored(Model model, HttpServletRequest request) {
        model.addAttribute("result", "fail");
        SystemAclUser user = (SystemAclUser) WebUtils.getSessionAttribute(request, SessionNames.LOGIN_USER);
        String cardCode = request.getParameter("cardCode");
        String authCode = request.getParameter("authCode");
        if (StringUtils.hasText(authCode)) {
            authCode = authCode.trim();
        }
        String payType = request.getParameter("payType");
        String physicalCode = request.getParameter("physicalCode");
        SystemPosMachine systemPosMachine = systemPosMachineService.findByPhysicalCode(physicalCode);
        if (systemPosMachine == null) {
            model.addAttribute("result", "fail");
            model.addAttribute("message", "pos机不存在");
            return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
        }
        systemPosMachine = autoMapper.mapperEntity(systemPosMachine);
        SystemPrinter systemPrinter = systemPosMachine.getReceiptPrinter();
        String amount = request.getParameter("amount");
        CardInfo cardInfo;
        CardCustomer cardCustomer;
        CardAccount cardAccount;
        if (!StringUtils.hasText(amount) || Double.parseDouble(amount) <= 0) {
            model.addAttribute("message", "充值金额不能为零");
            return JSONObject.toJSONString(model);
        }
        //查询顾客卡信息
        QueryWrapper<CardInfo> cardInfoWrapper = new QueryWrapper<>();
        cardInfoWrapper.eq("CARD_CODE", cardCode);
        cardInfoWrapper.eq("status", 0);
        cardInfo = cardInfoService.getOne(cardInfoWrapper);
        if (cardInfo == null) {
            model.addAttribute("message", "未找到该卡片所对应客户");
            return JSONObject.toJSONString(model);
        } else {
//            查询顾客信息
            QueryWrapper<CardCustomer> cardCustomerWrapper = new QueryWrapper<>();
            cardCustomerWrapper.eq("STATUS", 0);
            cardCustomerWrapper.eq("ID", cardInfo.getCustomerId());
            cardCustomer = cardCustomerService.getOne(cardCustomerWrapper);
            if (cardCustomer == null) {
                model.addAttribute("message", "账户已被冻结");
                return JSONObject.toJSONString(model);
            } else {
                //查询账户信息
                QueryWrapper<CardAccount> cardAccountWrapper = new QueryWrapper<>();
                cardAccountWrapper.eq("CUSTOMER_ID", cardInfo.getCustomerId());
                cardAccountWrapper.eq("ACCOUNT_TYPE_ID", CARD_ACCOUNT_TYPE_CHUZHI);
                cardAccountWrapper.eq("STATUS", 0);
                cardAccount = cardAccountService.getOne(cardAccountWrapper);
                if (cardAccount == null) {
                    model.addAttribute("message", "未找到该卡片所对应储值型账户(次数型账户不可进行本操作)");
                    return JSONObject.toJSONString(model);
                }
            }
        }
        //先存储流水
        TradeAccountStoreFlow tradeAccountStoreFlow = new TradeAccountStoreFlow();
        if (systemPosMachine != null) {
            tradeAccountStoreFlow.setPosMachineId(systemPosMachine.getId());
        }
        tradeAccountStoreFlow.setCustomerId(cardCustomer.getId());
        tradeAccountStoreFlow.setAccountId(cardAccount.getId());
        tradeAccountStoreFlow.setCardId(cardInfo.getId());
        tradeAccountStoreFlow.setOperateType(0);
        tradeAccountStoreFlow.setSettlementTypeId(SETTLEMENT_TYPE_ID_jiesuan);//结算
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss");
        tradeAccountStoreFlow.setFlowNo("STORE-" + df.format(LocalDateTime.now()) + UUID.randomUUID().toString().substring(0, 4));
        tradeAccountStoreFlow.setBeforeAmount(cardAccount.getAmount());
        tradeAccountStoreFlow.setAfterAmount(new BigDecimal(cardAccount.getAmount().doubleValue() + Double.parseDouble(amount)));
        tradeAccountStoreFlow.setBeforeTimes(0);
        tradeAccountStoreFlow.setAfterTimes(0);
        tradeAccountStoreFlow.setTimes(0);
        tradeAccountStoreFlow.setIsPay("0");//是否打印发票
        tradeAccountStoreFlow.setCreatorId(user.getId());
        tradeAccountStoreFlow.setCreatorName(user.getName());
        tradeAccountStoreFlow.setCreateTime(LocalDateTime.now());
        //判断支付方式
        if (StringUtils.hasText(authCode)) {
            if ("1".equals(payType)) {
                tradeAccountStoreFlow.setReasonId("支付宝储值");
                //支付宝支付
                // 支付超时，线下扫码交易定义为5分钟
                String timeoutExpress = "5m";
                // 创建条码支付请求builder，设置请求参数
                AlipayTradePayRequestBuilder builder = new AlipayTradePayRequestBuilder()
                        .setOutTradeNo(tradeAccountStoreFlow.getFlowNo())
                        .setSubject("goodsDetailList")
                        .setAuthCode(authCode)
                        .setTotalAmount(amount)
                        .setUndiscountableAmount("0.0")
                        .setTimeoutExpress(timeoutExpress);

                // 调用tradePay方法获取当面付应答
                AlipayF2FPayResult result = tradeService.tradePay(builder);
                switch (result.getTradeStatus()) {
                    case SUCCESS:
                        System.err.println("支付宝支付成功: )");
                        model.addAttribute("result", "success");
                        model.addAttribute("message", "储值成功");
                        tradeAccountStoreFlow.setActualAmount(new BigDecimal(amount));
                        tradeAccountStoreFlowService.save(tradeAccountStoreFlow);
                        //充值
                        cardAccount.setAmount(tradeAccountStoreFlow.getAfterAmount());
                        cardAccountService.updateById(cardAccount);
                        if (systemPrinter != null) {
                            //打印小票
                            smallTicketPrinter.printStoreOrder(tradeAccountStoreFlow, cardInfo, systemPrinter);
                        }
                        break;
                    case FAILED:
                        System.err.println("支付宝支付失败!!!");
                        System.err.println(result.getResponse().getBody());
                        model.addAttribute("message", "支付宝支付失败!!!");
                        break;
                    case UNKNOWN:
                        System.err.println("系统异常，订单状态未知!!!");
                        model.addAttribute("message", "系统异常，订单状态未知!!!");
                        break;

                    default:
                        System.err.println("不支持的交易状态，交易返回异常!!!");
                        model.addAttribute("message", "不支持的交易状态，交易返回异常!!!");
                        break;
                }
                return JSONObject.toJSONString(model);
            } else if ("2".equals(payType)) {
                //微信支付
                tradeAccountStoreFlow.setReasonId("微信储值");
                HashMap<String, String> map = new HashMap<>();
                String totalFee;
                try {
                    Float f = Float.parseFloat(amount) * 100;
                    totalFee = String.valueOf(f).substring(0, f.toString().indexOf('.'));
                    System.err.println("totalFee------" + totalFee);
                    map.put("total_fee", totalFee);
                } catch (Exception e) {
                    totalFee = "0";
                }
                map.put("spbill_create_ip", "123.12.12.123");
                map.put("auth_code", authCode);
                try {
                    WXPayConfigImpl config = WXPayConfigImpl.getInstance();
                    System.err.println("WX--------------1");
                    WXPay wxpay = new WXPay(config);
                    System.err.println("WX--------------2");
                    Map<String, String> microPay = wxpay.microPay(map);
                    System.err.println("WX----3-----microPsy" + microPay.toString());
                    // 判断是否成功
                    Map<String, String> ResultMap = isSuccess(microPay, wxpay, map);
                    System.err.println("map中issuccess值 ；" + ResultMap.get("is_success"));
                    int i = 0;
                    boolean b = false;
                    // 判断是否需要调取订单信息
                    while (i <= 5 && ResultMap.get("is_success") != null) {
                        System.err.println(i + "次" + ResultMap.get("is_success") + ResultMap);
                        if (ResultMap.get("is_success").equals("YES")) {
                            model.addAttribute("result", "success");
                            model.addAttribute("message", "储值成功");
                            tradeAccountStoreFlow.setActualAmount(new BigDecimal(amount));
                            tradeAccountStoreFlowService.save(tradeAccountStoreFlow);
                            //充值
                            cardAccount.setAmount(tradeAccountStoreFlow.getAfterAmount());
                            cardAccountService.updateById(cardAccount);
                            if (systemPrinter != null) {
                                //打印小票
                                smallTicketPrinter.printStoreOrder(tradeAccountStoreFlow, cardInfo, systemPrinter);
                            }
                            break;
                        } else if ("NO".equals(ResultMap.get("is_success"))) {
                            model.addAttribute("message", "支付失败");
                            return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
                        }
                        Thread.sleep(5000);
                        map.remove("auth_code");
                        Map<String, String> againData = new HashMap<>();
                        againData.put("appid", map.get("appid"));
                        againData.put("mch_id", map.get("mch_id"));
                        againData.put("out_trade_no", map.get("out_trade_no"));
                        againData.put("nonce_str", map.get("nonce_str"));
                        againData.put("sign", map.get("sign"));
                        ResultMap = wxpay.orderQuery(againData);
                        System.err.println("再次map" + ResultMap);
                        ResultMap = isSuccess(ResultMap, wxpay, map);
                        i++;
                    }
                    if (i == 6) {
                        Map<String, String> reverseMap = new HashMap<>();
                        reverseMap.put("appid", map.get("appid"));
                        reverseMap.put("mch_id", map.get("mch_id"));
                        reverseMap.put("out_trade_no", map.get("out_trade_no"));
                        reverseMap.put("nonce_str", map.get("nonce_str"));
                        reverseMap.put("sign", map.get("sign"));
                        Map<String, String> reverse = wxpay.reverse(reverseMap);
                        if (reverse.get("result_code").equals("SUCCESS") && reverse.get("return_code").equals("SUCCESS")) {
                            System.err.println("订单已取消");
                            model.addAttribute("message", "订单已取消!!!");
                            return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
                        }
                    }
                    System.err.println("结果===============" + ResultMap);
                    return JSONObject.toJSONString(model);
                } catch (Exception e) {
                    System.err.println("e=====" + e);
                    e.printStackTrace();
                    model.addAttribute("message", "交易异常!!!");
                    return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
                }
            }
        } else if ("0".equals(payType)) {
            //现金支付
            tradeAccountStoreFlow.setReasonId("现金储值");
            model.addAttribute("result", "success");
            model.addAttribute("message", "储值成功");
            tradeAccountStoreFlow.setActualAmount(new BigDecimal(amount));
            tradeAccountStoreFlowService.save(tradeAccountStoreFlow);
            //充值
            cardAccount.setAmount(tradeAccountStoreFlow.getAfterAmount());
            cardAccountService.updateById(cardAccount);
            if (systemPrinter != null) {
                //打印小票
                smallTicketPrinter.printStoreOrder(tradeAccountStoreFlow, cardInfo, systemPrinter);
            }
            return JSONObject.toJSONString(model);
        }
        model.addAttribute("message", "储值失败");
        return JSONObject.toJSONString(model);
    }

    public Map<String, String> isSuccess(Map<String, String> map, WXPay wxpay, Map<String, String> data) {
        if (map.get("return_code").equals("SUCCESS")) {// 通讯成功
            if (map.get("result_code").equals("SUCCESS")) {// 交易成功
                if (map.get("trade_state") == null) {
                    map.put("is_success", "YES");
                    System.err.println("111 ===" + map.get("is_success"));
                } else if (map.get("trade_state").equals("USERPAYING")) {
                    map.put("is_success", "UNKNOWN");
                    System.err.println("222 ===" + map.get("is_success"));
                } else if (map.get("trade_state").equals("SUCCESS")) {
                    map.put("is_success", "YES");
                    System.err.println("333 ===" + map.get("is_success"));
                }
                return map;
            } else if (map.get("result_code").equals("FAIL")) {
                String errCode = map.get("err_code");// 交易不明确,查询订单
                if (errCode.equals("USERPAYING") || errCode.equals("BANKERROR") || errCode.equals("SYSTEMERROR")) {
                    map.put("is_success", "UNKNOWN");
                    System.err.println("444 ===unKnown");
                    return map;
                }
            }
            System.err.println("555 ===FAIL");
            map.put("is_success", "NO");
            return map;
        } else {
            System.err.println("支付失败，请重新扫码! 666===FAIL");
            map.put("is_success", "NO");
            return map;
        }
    }

}
